package org.origin.common.utils;

import org.origin.common.exception.ServiceException;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @author 11411
 */
public class ToolsUtils {


    private final static String PATTERN = "\\s*|\t|\r|\n";

    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }

    /**
     * 对象是否为空
     *
     * @author
     * @Date 2018/3/18 21:57
     */
    public static boolean isEmpty(Object o) {
        if (o == null) {
            return true;
        }
        if (o instanceof String) {
            if (o.toString().trim().isEmpty()) {
                return true;
            }
        } else if (o instanceof List) {
            if (((List<?>) o).isEmpty()) {
                return true;
            }
        } else if (o instanceof Map) {
            if (((Map<?, ?>) o).isEmpty()) {
                return true;
            }
        } else if (o instanceof Set) {
            if (((Set<?>) o).isEmpty()) {
                return true;
            }
        } else if (o instanceof Object[]) {
            if (((Object[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof int[]) {
            if (((int[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof long[]) {
            if (((long[]) o).length == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查类型是否为Long
     * @param num
     * @return
     */
    public static boolean isLong(String num){
        try{
            Long retNums = Long.parseLong(num);
        }catch (Exception e){
            return false;
        }
        return true;
    }

    public static String replaceBlank(String str){
        String dest = null;
        if(str == null){
            return dest;
        }else{
            Pattern p = Pattern.compile(PATTERN);
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
            return dest;
        }
    }

    /**
     * 替换中间字符
     * @param param
     * @param str
     * @return
     */
    public static String hideChar(String param,String str){
        StringBuilder sb = new StringBuilder();
        for(int i = 0;i<param.length(); i++){
            if(i == 0){
                sb.append(param.charAt(i));
            }else if(i == 1){
                sb.append(param.charAt(i));
            }else if(i == param.length()-9){
                sb.append(param.charAt(i));
            }else if(i == param.length()-3){
                sb.append(param.charAt(i));
            }else if(i == param.length()-2){
                sb.append(param.charAt(i));
            }else if(i == param.length()-1){
                sb.append(param.charAt(i));
            }else{
                sb.append(str);
            }
        }
        return sb.toString();
    }

    public static String addZeroForNum(String str, int strLength,int type) {
        int strLen = str.length();
        if (strLen < strLength) {
            while (strLen < strLength) {
                StringBuilder sb = new StringBuilder();
                if(type==1){
                    //前面加
                    sb.append("0").append(str);
                }else{
                    //后面加
                    sb.append(str).append("0");
                }
                str = sb.toString();
                strLen = str.length();
            }
        }
        return str;
    }

    /**
     * 驼峰转下划线
     * @param camelCaseStr
     * @return
     */
    public static String camelToUnderline(String camelCaseStr) {
        Pattern humpPattern = Pattern.compile("[A-Z]");
        Matcher matcher = humpPattern.matcher(camelCaseStr);
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


    /**
     * 首字母转大写
     * @param str
     * @return
     */
    public static String firstLetterToUpper(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * list转map
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, Object> toMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        Class<?> clazz = obj.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true); // 使得私有字段也可以访问
            try {
                map.put(field.getName(), field.get(obj));
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return map;
    }

    /**
     * 去掉字符串末尾的标点符号
     * @param str
     * @return
     */
    public static String removePunctuationAtEnd(String str) {
        if (isEmpty(str)) {
            return str;
        }
        // 使用正则表达式去掉字符串末尾的指定标点符号
        return str.replaceAll("[.,;!?。！？；]+$", "");
    }

    /**
     * 对比两个对象各属性的值,并将值不相等的属性实例化为新对象
     * @param t1 对比标准对象(定值)
     * @param t2 对比对象(对比值)
     * @return 对比结果对象(数值来源于t2)
     * @param <T>
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    public static <T> T compareAndCreateNew(T t1, T t2) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        if (t1 == null || t2 == null) {
            return null;
        }

        Class<?> clazz = t1.getClass();
        if (!clazz.equals(t2.getClass())) {
            throw new ServiceException(500,"The two objects must be of the same type.");
        }

        T result = (T) clazz.getDeclaredConstructor().newInstance();

        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            Object value1 = field.get(t1);
            Object value2 = field.get(t2);

            if (!Objects.equals(value1, value2)) {
                if (value1 != null && value2 != null && !field.getType().isPrimitive()) {
                    // 对于非基础类型的字段，递归调用
                    Object nestedResult = compareAndCreateNew(value1, value2);
                    field.set(result, nestedResult);
                } else {
                    // 设置第二个对象的值
                    field.set(result, value2);
                }
            }
        }

        return result;
    }

    /**
     * 对比两个对象各属性的值,并将值不相等的属性新旧值返回
     * @param t1 "旧值"
     * @param t2 "新值"
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, Map<String, Object>> compareAndCreateMap(Object t1, Object t2) throws IllegalAccessException {
        Map<String, Map<String, Object>> diffMap = new HashMap<>();

        if (t1 == null || t2 == null) {
            throw new ServiceException(500,"Both objects must be non-null.");
        }

        Class<?> clazz = t1.getClass();
        if (!clazz.equals(t2.getClass())) {
            throw new ServiceException(500,"The two objects must be of the same type.");
        }

        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            Object value1 = field.get(t1);
            Object value2 = field.get(t2);

            if (!Objects.equals(value1, value2)) {
                Map<String, Object> valueMap = new HashMap<>();
                valueMap.put("old", value1);
                valueMap.put("new", value2);
                diffMap.put(field.getName(), valueMap);
            }
        }

        return diffMap;
    }

    /**
     * 对比两个对象各属性的值,返回值不同的属性名称
     * @param t1
     * @param t2
     * @return
     * @throws IllegalAccessException
     */
    public static List<String> getDifferentFields(Object t1, Object t2) throws IllegalAccessException {
        List<String> differentFields = new ArrayList<>();

        if (t1 == null || t2 == null) {
            throw new ServiceException(500,"Both objects must be non-null.");
        }

        Class<?> clazz = t1.getClass();
        if (!clazz.equals(t2.getClass())) {
            throw new ServiceException(500,"The two objects must be of the same type.");
        }

        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            Object value1 = field.get(t1);
            Object value2 = field.get(t2);

            if (!Objects.equals(value1, value2)) {
                differentFields.add(field.getName());
            }
        }

        return differentFields;
    }

}
